using System;
using System.Collections.Generic;
using System.Net;
using System.Web;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using MediaPortal.GUI.Library;
using MediaPortal.Configuration;
using Rss;
using System.Text.RegularExpressions;

namespace MP_RSSTicker
{
    /// <summary>
    /// Process plugin that reeds news items from a live RSS Feed and provides it
    /// to the GUI to be used as a RSS Ticker.
    /// </summary>
    public class RSSTicker : IPlugin, ISetupForm
    {
        public RSSTicker()
        {
        }

        #region ISetupForm Members

        /// <summary>
        /// Returns the name of the plugin which is shown in the plugin menu
        /// </summary>
        /// <returns>the name of the plugin which is shown in the plugin menu</returns>
        public string PluginName()
        {
            return "MP-RSSTicker";
        }

        /// <summary>
        /// Returns the description of the plugin which is shown in the plugin menu
        /// </summary>
        /// <returns>the description of the plugin which is shown in the plugin menu</returns>
        public string Description()
        {
            return "Proces plugin that reads a RSS feed and provides it for usage on screen";
        }

        /// <summary>
        /// Returns the author of the plugin which is shown in the plugin menu
        /// </summary>
        /// <returns>the author of the plugin which is shown in the plugin menu</returns>
        public string Author()
        {
            return "Sambal";
        }

        /// <summary>
        /// Indicates whether plugin can be enabled/disabled
        /// </summary>
        public void ShowPlugin()
        {
            ConfigurationForm configurationForm = new ConfigurationForm();
            configurationForm.ShowDialog();
        }

        /// <summary>
        /// Indicates whether plugin can be enabled/disabled
        /// </summary>
        /// <returns>true if the plugin can be enabled/disabled</returns>
        public bool CanEnable()
        {
            return true;
        }

        /// <summary>
        /// Get Windows-ID
        /// </summary>
        /// <returns>unique id for this plugin</returns>
        public int GetWindowId()
        {
            // WindowID of windowplugin belonging to this setup
            // enter your own unique code
            return 9729;
        }

        /// <summary>
        /// Indicates if plugin is enabled by default
        /// </summary>
        /// <returns>true if this plugin is enabled by default</returns>
        public bool DefaultEnabled()
        {
            return true;
        }

        /// <summary>
        /// indicates if a plugin has its own setup screen
        /// </summary>
        /// <returns>true if the plugin has its own setup screen</returns>
        public bool HasSetup()
        {
            return true;
        }

        /// <summary>
        /// no Home for this plugin, return false
        /// </summary>
        /// <param name="strButtonText"></param>
        /// <param name="strButtonImage"></param>
        /// <param name="strButtonImageFocus"></param>
        /// <param name="strPictureImage"></param>
        /// <returns></returns>
        public bool GetHome(out string strButtonText, out string strButtonImage,
                            out string strButtonImageFocus, out string strPictureImage)
        {
            strButtonText = String.Empty;
            strButtonImage = String.Empty;
            strButtonImageFocus = String.Empty;
            strPictureImage = String.Empty;
            return false;
        }


        #endregion

        /// <summary>
        /// Timer to handle auto refresh
        /// </summary>
        private TimerCallback rssUpdateTimer = null;

        /// <summary>
        /// URL of the feed to display
        /// </summary>
        private string feedURL = "";

        /// <summary>
        /// Path to image to display
        /// </summary>
        private string feedIMG = "";

        /// <summary>
        /// Number of items to retrieve
        /// </summary>
        private int numberOfItems = 10;

        /// <summary>
        /// Item separator
        /// </summary>
        private string separator = "::";

        /// <summary>
        /// Flag to indicate whether or not to auto refresh feed
        /// </summary>
 
        private bool autoRefresh = false;

        /// <summary>
        /// Interval in minutes between refresh if autoRefresh enabled
        /// </summary>
        private int autoRefreshInterval = 15;

        /// <summary>
        /// Time of last check
        /// </summary>
        private DateTime lastRefreshCheck = DateTime.MinValue;

        /// <summary>
        /// Timer that handles calls to update method
        /// </summary>
        private System.Threading.Timer refreshTimer = null;

        /// <summary>
        /// Start this proces plugin. Initializes needed member variables
        /// </summary>
        public void Start()
        {
            Log.Info("RSS Feed proces started");
            using (MediaPortal.Profile.Settings xmlreader = new MediaPortal.Profile.Settings(Config.GetFile(Config.Dir.Config, "MediaPortal.xml")))
            {
                // Read user settings from configuration file
                feedURL = xmlreader.GetValueAsString("RSSFeeds", "feedURL", "");
                feedIMG = xmlreader.GetValueAsString("RSSFeeds", "feedIMG", "");
                GUIPropertyManager.SetProperty("#rssimg", feedIMG);
                numberOfItems = int.Parse(xmlreader.GetValueAsString("RSSFeeds", "nbItems", "10"));
                separator = xmlreader.GetValueAsString("RSSFeeds", "separator", "::");

                autoRefresh = false;
                if (xmlreader.GetValueAsInt("RSSFeeds", "autoRefresh", 0) != 0)
                    autoRefresh = true;
                autoRefreshInterval = int.Parse(xmlreader.GetValueAsString("RSSFeeds", "autoRefreshInterval", "15"));
            }
            // If no feed selected through config show default config message
            if (feedURL == "")
            {
                GUIPropertyManager.SetProperty("#rssfeed", "Please run RSS Feeds configuration to configure feeds.");
            }
            else
            {
                UpdateNews();
                Log.Debug("MP-RSSTicker autoRefresh = " + autoRefresh);
                Log.Debug("MP-RSSTicker interval    = " + autoRefreshInterval);
                if (autoRefresh)
                {
                    //Call UpdateFeedTimer every minute
                    rssUpdateTimer = new TimerCallback(UpdateFeedTimer);
                    refreshTimer = new System.Threading.Timer(rssUpdateTimer, null, 60000, 60000);
                }
            }
        }

        /// <summary>
        /// Stop this proces plugin
        /// </summary>
        public void Stop()
        {
        }

        /// <summary>
        /// Timer method. 
        /// </summary>
        /// <param name="stateInfo"></param>
        public void UpdateFeedTimer(Object stateInfo)
        {
            Log.Debug("MP-RSSTicker UpdateFeedTimer called");
            TimeSpan tsUpdate = DateTime.Now - lastRefreshCheck;
            if ((int)tsUpdate.TotalMinutes > autoRefreshInterval)
            {
                Log.Debug("MP-RSSTicker auto updating feed");
                lastRefreshCheck = DateTime.Now;
                UpdateNews();
            }
        }

        /// <summary>
        /// Update the actual news items from the live feed
        /// </summary>
        public void UpdateNews()
        {
            try
            {
                if (feedURL.ToLower().StartsWith("http://") == false && feedURL.ToLower().StartsWith("file://") == false)
                {
                    feedURL = "http://" + feedURL;
                }
                Uri newURL = new Uri(feedURL);
                Download(newURL);
            }
            catch (Exception ex)
            {
                Log.Error("MP-RSSTicker error reading feed: " + feedURL);
            }
        }

        /// <summary>
        /// Download the actual feed items and create item string
        /// Large copy/paste action from News plugin provided by MediaPortal
        /// </summary>
        /// <param name="location">Feed URL to download</param>
        /// <returns>true when no exception occurred</returns>
        bool Download(Uri location)
        {
            int i = 0;
            Uri uri = location;
            string itemString = "";


            try
            {
                RssFeed feed = RssFeed.Read(location.ToString());
                Rss.RssChannel channel = (Rss.RssChannel)feed.Channels[0];

                // Fill the items
                foreach (Rss.RssItem item in channel.Items)
                {
                    // Check if there are HTML tags in the description, if so we need to "parse" the HTML
                    // which is actually just stripping the tags.
                    if (Regex.IsMatch(item.Description, @"<[^>]*>"))
                    {
                        // Strip \n's
                        item.Description = Regex.Replace(item.Description, @"(\n|\r)", "", RegexOptions.Multiline);

                        // Remove whitespace (double spaces)
                        item.Description = Regex.Replace(item.Description, @"  +", "", RegexOptions.Multiline);

                        // Replace <br/> with \n
                        item.Description = Regex.Replace(item.Description, @"< *br */*>", "\n", RegexOptions.IgnoreCase & RegexOptions.Multiline);

                        // Remove remaining HTML tags
                        item.Description = Regex.Replace(item.Description, @"<[^>]*>", "", RegexOptions.Multiline);
                    }

                    // Strip newlines from titles because it looks funny to see multiple lines in the listbox
                    item.Title = Regex.Replace(item.Title, @" *(\n|\r)+ *", " ", RegexOptions.Multiline);

                    if (item.Description == "")
                    {
                        item.Description = item.Title;
                    }
                    else
                    {
                        item.Description = item.Title + ": \n\n" + item.Description + "\n";
                    }

                    i++;
                    if (i >= numberOfItems)
                        break;
                    itemString += item.Title + " " + separator + " ";
                }

            }
            catch (WebException ex)
            {
                Log.Error("MP-RSSTicker error reading feed", ex);
            }

            // Make sure that everything is "decoded" like &amp; becomes &
            itemString = HttpUtility.HtmlDecode(itemString);

            // Provide items to GUI
            GUIPropertyManager.SetProperty("#rssfeed", itemString);
            return true;
        }
    }
}
